-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Feature post release hook #438
base: master
Are you sure you want to change the base?
Conversation
If the crate handles it, then its not our problem :)
My thoughts
One option is to have a dummy project to release with hooks that print messages. We then use |
The way I set it up is that
Sounds good. Does this also mean that the release shouldn't be yanked on failure?
Sounds good. |
What if we provide the tag instead?
Yes, let's leave all failure policy to the script |
Oh, have you looked at how other release processes from other ecosystems deal with this? I'm assuming there is similar for node and others. We should make a list of them to regularly consult for ideas. |
I added this function which gets the head sha. I'm not sure what to do if it fails. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to publish these
src/release.rs
Outdated
if !cmd::call_with_env(post_rel_hook, envs, cwd, false)? { | ||
todo!("handle non-zero exit from post-release hook") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should happen if the post-release hook exits non-zero? I think it makes sense to say that the hook is responsible for rolling back any changes it made and any changes made in the pre-release hook. Maybe cargo-release should yank the new release if it was already made?
I think we should log the error as a warning and document it as no-fail
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should log the error as a warning and document it as no-fail
I'm not so sure about that. If that's the desired behavior, the hook can do that. I think it should be up to the hook to decide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm torn on this one. For a high quality one, they will write it out. For what most people will probably write, the assistance could be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we let it fail and add an error message stating that the hook should convert the error to a warning if that's the desired behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, the hook, if its handling errors, can decide whether to give an error exit code.
Let's go ahead and warn if the hook fails but we shouldn't be telling people what to do about the hook.
?? |
I looked briefly at npm. They have all the |
e50cb1a
to
811dd46
Compare
I've made the changes we discussed and added two failing tests. The hook does not run. I tried to copy the same logic that determines when to run the pre-release hook. I'm not sure where I went wrong. |
1 similar comment
I've made the changes we discussed and added two failing tests. The hook does not run. I tried to copy the same logic that determines when to run the pre-release hook. I'm not sure where I went wrong. |
// STEP 7: git push | ||
// STEP 7: post-release hook | ||
for pkg in pkgs { | ||
if let (Some(post_rel_hook), Some(_)) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@epage, I think this if
statement isn't checking the right thing. I don't know what it should be checking. Can you advise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests are not doing a version bump and most of actions are only on version bump.
let post_rel_hook = post_rel_hook.args(); | ||
log::debug!("Calling post-release hook: {:?}", post_rel_hook); | ||
let envs = maplit::btreemap! { | ||
OsStr::new("RELEASE_TAG") => OsStr::new(pkg.tag.as_ref().expect("post-release hook with no tag")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend we be consistent with the placholders: https://github.com/crate-ci/cargo-release/blob/master/docs/reference.md#placeholders
log::debug!("Calling post-release hook: {:?}", post_rel_hook); | ||
let envs = maplit::btreemap! { | ||
OsStr::new("RELEASE_TAG") => OsStr::new(pkg.tag.as_ref().expect("post-release hook with no tag")), | ||
OsStr::new("DRY_RUN") => OsStr::new(if dry_run { "true" } else { "false" }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come a lot of the pre-release variables were removed?
@@ -0,0 +1,132 @@ | |||
use assert_fs::prelude::*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer this to be tests/post-release-hook.rs
@@ -0,0 +1 @@ | |||
../crate/.gitignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please store all of these in the test/fixtures
directory
} | ||
|
||
fn git(dir: &Path, args: &[&str]) { | ||
assert!(Command::new("git") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
snapbox::cmd::Command
might be a good option
fn run_cargo_release(dir: &Path) -> String { | ||
let temp = TempDir::new().unwrap(); | ||
temp.copy_from(dir, &["**"]).unwrap(); | ||
|
||
git(temp.path(), &["init"]); | ||
git(temp.path(), &["add", "."]); | ||
git( | ||
temp.path(), | ||
&["commit", "--message", "this is a commit message"], | ||
); | ||
|
||
let mut cargo = env::var_os("CARGO").map_or_else(|| Command::new("cargo"), Command::new); | ||
let output = cargo | ||
.stderr(Stdio::piped()) | ||
.args(["run", "--manifest-path"]) | ||
.arg(Path::new(PROJECT_ROOT).join("Cargo.toml")) | ||
.args(["--", "release", "-vv"]) | ||
.current_dir(&temp) | ||
.spawn() | ||
.unwrap() | ||
.wait_with_output() | ||
.unwrap(); | ||
|
||
temp.close().unwrap(); | ||
|
||
if !output.status.success() { | ||
panic!("cargo release exited with {}", output.status); | ||
} | ||
let output = String::from_utf8(output.stderr).unwrap(); | ||
eprintln!("{output}"); | ||
output | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use snapbox::cmd::Command
and snapbox::cmd::cargo_bin!
fn run_cargo_release(dir: &Path) -> String { | ||
let temp = TempDir::new().unwrap(); | ||
temp.copy_from(dir, &["**"]).unwrap(); | ||
|
||
git(temp.path(), &["init"]); | ||
git(temp.path(), &["add", "."]); | ||
git( | ||
temp.path(), | ||
&["commit", "--message", "this is a commit message"], | ||
); | ||
|
||
let mut cargo = env::var_os("CARGO").map_or_else(|| Command::new("cargo"), Command::new); | ||
let output = cargo | ||
.stderr(Stdio::piped()) | ||
.args(["run", "--manifest-path"]) | ||
.arg(Path::new(PROJECT_ROOT).join("Cargo.toml")) | ||
.args(["--", "release", "-vv"]) | ||
.current_dir(&temp) | ||
.spawn() | ||
.unwrap() | ||
.wait_with_output() | ||
.unwrap(); | ||
|
||
temp.close().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have reusable fixture initialization, I'd recommend splitting that out into a dedicated function and have each test call cargo-release in its own way. This will make it easier to add new test cases in the future
|
||
fn main() { | ||
eprintln!("START_ENV_VARS"); | ||
for (key, value) in env::vars_os() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we ensure these are sorted, we can use snapbox
s built-in snapshot testing
We'd just define the following and snapbox's asserter will take the ...
and treat it as a multi-line wildcard.
START_ENV_VARS
...
DRY_RUN=true
...
RELEASE_TAG=post-release-hook-ws-a-v42.42.42
...
END_ENV_VARS
Here's my first crack at it. It needs some work, but I'm submitting it for feedback.
Open Questions
RELEASE_SHA
.RELEASE_TAG
andDRY_RUN
git rev-parse HEAD
to get the release commit fails? It should probably exit non-zero, but I see that you use specific exit codes. So the question is basically, what exit code?cargo-release
should yank the new release if it was already made?trycmd
orsnapbox
.Todo
post-release-hook
todocs/reference.md